package cn.tuling.dynamic;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DynamicProxyTest {
    public static void main(String[] args) {
        /*Subject realSubject = new RealSubject();
        MyInvocationHandler myInvocationHandler = new MyInvocationHandler(realSubject);
        Subject proxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), myInvocationHandler);
        String display = proxy.display();
        System.out.println(display);*/

        Subject proxy = DynamicProxy.getProxy(new RealSubject());
        String display = proxy.display();
        System.out.println(display);

        Subject proxy2 = DynamicProxy.getProxy(new RealSubject2());
        String display2 = proxy2.display();
        System.out.println(display2);
    }
}

interface Subject {
    String display();
}

class RealSubject implements Subject {

    @Override
    public String display() {
        return "RealSubject1";
    }
}

class RealSubject2 implements Subject {

    @Override
    public String display() {
        return "RealSubject2";
    }
}

class MyInvocationHandler<T> implements InvocationHandler {
    private T target;

    public MyInvocationHandler(T subject) {
        this.target = subject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("前置通知");
        return method.invoke(target, args);
    }
}

class DynamicProxy {
    public static <T> T getProxy(T target) {
        MyInvocationHandler<T> myInvocationHandler = new MyInvocationHandler<>(target);

        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), myInvocationHandler);
    }
}